#include "include/sht31.h"

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/i2c.h"
#include "esp_log.h"
#include "user_iic.h"


/* 描述：向SHT30发送一条16bit指令
 * 参数cmd：SHT30指令（在SHT30_MODE中枚举定义）
 * 返回值：成功返回ESP_OK                     */
static esp_err_t SHT3x_Send_Cmd(uint16_t sht3x_cmd)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, SHT3X_DeviceAddr | WRITE_BIT, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, sht3x_cmd>>8, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, sht3x_cmd&0xFF, ACK_CHECK_EN);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(I2C_EXAMPLE_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);

	return ret;
}

/* 描述：从SHT3x读取数据
 * 参数data_len：读取多少个字节数据
 * 参数data_arr：读取的数据存放在一个数组里
 * 返回值：读取成功返回ESP_OK
*/
static esp_err_t SHT3x_Recv_Data(uint8_t data_len, uint8_t* data_arr)
{
	i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, SHT3X_DeviceAddr | READ_BIT, ACK_CHECK_EN);
    if (data_len > 1) {
        i2c_master_read(cmd, data_arr, data_len - 1, ACK_VAL);
    }
    i2c_master_read_byte(cmd, data_arr + data_len - 1, NACK_VAL);
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(I2C_EXAMPLE_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);

	return ret;
}

static uint8_t SHT31_crc8(const uint8_t *data, int len)
{
/*
 * CRC-8 formula from page 14 of SHT spec pdf
 * Test data 0xBE, 0xEF should yield 0x92
 * Initialization data 0xFF
 * Polynomial 0x31 (x8 + x5 +x4 +1)
 * Final XOR 0x00
 */
  const uint8_t POLYNOMIAL = 0x31;
  uint8_t crc = 0xFF;
  for ( int j = len; j; --j ) {
      crc ^= *data++;
      for ( int i = 8; i; --i ) {
    	  crc = ( crc & 0x80 ) ? (crc << 1) ^ POLYNOMIAL : (crc << 1);
      }
  }
  return crc;
}

/* 描述：读取传感器编号
 * 参数：存储编号数据的指针
 * 返回值：0-读取成功，1-读取失败 */
static uint8_t SHT3x_ReadSerialNumber(uint32_t* serialNumber)
{
	uint8_t Num_buf[4] = {0xFF,0xFF,0xFF,0xFF};

	SHT3x_Send_Cmd(SHT31_READ_SERIAL_NUMBER);
	vTaskDelay(100 / portTICK_PERIOD_MS);   /* 延时50ms，有问题时需要适当延长！！！！！！*/
	esp_err_t ret = SHT3x_Recv_Data(4,Num_buf);

	*serialNumber = ((Num_buf[0] << 24) | (Num_buf[1] << 16) |(Num_buf[2] << 8) |(Num_buf[3]));
	if(0xFFFFFFFF == *serialNumber) return 1;
    else if(ret == ESP_OK) return 0;
    printf("SHT3x_ReadSerialNumber ERR :%s\n",esp_err_to_name(ret));
    return ret;
}

void SHT31_ModeSet(void)
{
	uint32_t data_ID;
	/* 读取SHT3x的SerialNumber值 */
	if(SHT3x_ReadSerialNumber(&data_ID) == 0)
		printf("Read SHT31_SerialNumber 0k: 0x%x \n",data_ID);
	else
		printf("Read SHT31_SerialNumber err: 0x%x \n",data_ID);

	SHT3x_Send_Cmd(SHT31_LOW_1_CMD);
}

uint8_t SHT31_ReadTempHum(float *data)
{
	uint8_t readbuffer[6];

	SHT3x_Send_Cmd(SHT31_READOUT_FOR_PERIODIC_MODE);
	vTaskDelay(10/portTICK_PERIOD_MS);
	SHT3x_Recv_Data(6,readbuffer);

	uint16_t ST, SRH;
	ST = readbuffer[0]<<8 | readbuffer[1];
	if (readbuffer[2] != SHT31_crc8(readbuffer, 2)) return 0x01;

	SRH = readbuffer[3]<<8 | readbuffer[4];
	if (readbuffer[5] != SHT31_crc8(readbuffer+3, 2)) return 0x02;

	// Serial.print("ST = "); Serial.println(ST);
	data[0] = (175.0*(double)ST/65535.0-45.0);

	//  Serial.print("SRH = "); Serial.println(SRH);
	data[1] = (100.0*(double)SRH/65535.0);;

	return 0x00;
}
